#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
Модуль осуществляет поиск по методу Гзовского ориентации 
векторов главных напряжений по заданным ориентировкам 
двух сопряженных плоскостей.
"""

import sys
from optparse import OptionParser
from plane import Plane
import fr_parser

def f(a, b):
    # Функция возвращает True если a впереди попходу часовой стрелки от b
    return (a-b)%360<180
def f2(a, b, c):
    # Функция возвращает True если a,b,c стоят друг за другом по часовой стрлке
    list = [a,b,c]
    list.sort()
    if list==[a,b,c] or list==[b,c,a] or list==[c,a,b]:
        return True
    else:
        return False

# Parsing of an options
optparser= OptionParser()
optparser.add_option('-o', '--output filename', dest='ofile',
                     help='Name of a file to put the results in a \
					 str_canvas format')                     
optparser.add_option('-c', dest='dirs',
					help='Read directions in files', 
					action='store_true',
                    default=False)				
options, args = optparser.parse_args(sys.argv[1:])

lines = sys.stdin.read().split('\n')

# Разбор введенных данных и создание двух плоскостей Sc1 и Sc2.

data=[]
for line in lines:
    val = fr_parser.parse_line(line)
    if val: data.append(val)    
Sc1 = Plane(int(data[0][0]), int(data[0][1]))
Sc2 = Plane(int(data[1][0]), int(data[1][1]))
if options.dirs:
    dir2 = int(data[1][2])
    dir1 = int(data[0][2])

# Находим линию пересечения сопряженных плоскостей.
Sc1_n = Sc1.normal()
Sc2_n = Sc2.normal()
L_2 = Sc1_n.get_perpendicular_between(Sc2_n)

# Находим плоскость перпендикулярную обоим сопряженным плоскостям.
Sv = L_2.normal()

# Находим линии пересечения плоскости Sv и сопряженных плоскостей.
Sv_n = Sv.normal()
Lj1 = Sv_n.get_perpendicular_between(Sc1_n)
Lj2 = Sv_n.get_perpendicular_between(Sc2_n)

# Находим угол между линиями пересечения Lj1 и Lj2 и направлением падения плоскости Sv
a1 = Sv.return_angle_between(Lj1) 
a2 = Lj1.return_angle_between(Lj2) 
a3 = Sv.return_angle_between(Lj2) 

# Поворачиваем Sv вдоль плоскости чтобы он стал ровно посередине между сопряженными плоскостями
# Сторона в которую поворачиваем плоскость, зависит от того, которая из линий Lj ближе
# В результате L_1 будет более наклоненной чем L_3. Мы исправим это в дальнейшем
if a1<a3:
    L_1 = Sv.rotated(a1 + .5*a2)
else:
    L_1 = Sv.rotated(a3 + .5*a2)

# Находим последнюю линию, перпендикулярную двум найденым
L_3 = L_1.get_perpendicular_between(L_2)

if not options.dirs:
    # L_3 должна быть биссектрисой острого угла, образованного Lj1 и Lj2
    a1 = L_3.return_angle_between(Lj1) 
    a3 = 180 - L_3.return_angle_between(Lj2) 
    if (a1 + a3) > 90:
        L_3, L_1 = L_1, L_3

# Проверяем положение линий в нижней полусфере
if L_1.dip < 0 :
    L_1.dip=-1*L_1.dip
    L_1.dir+=180
    L_1.dir=L_1.dir%360
if L_2.dip < 0 :
    L_2.dip=-1*L_2.dip
    L_2.dir+=180
    L_2.dir=L_2.dir%360
if L_3.dip < 0 :
    L_3.dip=-1*L_3.dip
    L_3.dir+=180
    L_3.dir=L_3.dir%360
    

# Если не указанa опция -c, то проверяем положение оси растяжения. Ось растяжения должна находиться между двумя сопряженными плоскостями, так чтобы она была в направлении движения часовой стрелки от первой плоскости, и далльше в направлении движения часовой стрелки от оси растяжения следует вторая сопряженная ось.
# Иначе проверяем направление смещений


if options.dirs:
    sys.stderr.write('-------\n')
    sys.stderr.write('%s %s %s %s\n' % (Sc1, dir1, Sc2, dir2))
    sys.stderr.write('%s %s %s\n' % ( L_1, L_2, L_3))
    # Определяем, как напралвены смещения максимумов (навстречу друг другу или нет)
    pplane = Sc1.normal().get_perpendicular_between(Sc2.normal()).normal()
    ppA = max((pplane.dir)%360, (pplane.dir+180)%360)
    ppB = ppA - 180
    sys.stderr.write('%003d %003d\n' % (ppA, ppB))
    if f2(ppA,dir1,ppB) and f2(ppB,dir2,ppA): 
        # направлены в стороны друг от друга <--*  *-->
        sys.stderr.write('<--* *-->\n')
        if    f2(Sc1.dir, L_3.dir, Sc2.dir):
            pass
        elif  f2(Sc1.dir, L_1.dir, Sc2.dir):
            L_1,L_3 = L_3,L_1
        else:
            sys.stderr.write('Error!\n')
    elif f2(ppA,dir2,ppB) and f2(ppB,dir1,ppA): 
        # направлены друг к другу            *-->  <--*
        sys.stderr.write('*--> <--*\n')
        if    f2(Sc1.dir, L_1.dir, Sc2.dir):
            pass
        elif  f2(Sc1.dir, L_3.dir, Sc2.dir):
            L_1,L_3 = L_3,L_1
        else:
            sys.stderr.write('Error!\n')
    else:
        sys.stderr.write('Error! Cannot find stress axes\n')
        sys.exit()

    # Вывод результата на экран и в файл
    sys.stdout.write('sigma1   sigma2   sigma3\n')
    sys.stdout.write('%003d %02d   %003d %02d   %003d %02d\n' % (L_1.dir, L_1.dip, L_2.dir, L_2.dip, L_3.dir, L_3.dip))

    if options.ofile:
        f = open(options.ofile, 'w')
        f.write('%003d %02d l\n' % (Sc1.dir, Sc1.dip))
        f.write('%003d %02d l\n' % (Sc2.dir, Sc2.dip))
        f.write('%003d 90 l\n' % (Sc1.dir))
        f.write('%003d 90 l\n' % (Sc2.dir))
        # draw small arrows
        if L_2.dip < 20:
            # draw just one aroow
            A = (Sc1.dir-90)%360
            B = (Sc1.dir+90)%360
            if (B-dir1)%360<180 and (A-dir1)%360>180:
                f.write('%003d %02d %003d w\n' % (Sc1.dir, Sc1.dip, Sc1.dir))
            else:
                f.write('%003d %02d %003d w\n' % (Sc1.dir, Sc1.dip, (Sc1.dir+180)%360))
            A = (Sc2.dir-90)%360
            B = (Sc2.dir+90)%360
            if (B-dir2)%360<180 and (A-dir2)%360>180:
                f.write('%003d %02d %003d w\n' % (Sc2.dir, Sc2.dip, Sc2.dir))
            else:
                f.write('%003d %02d %003d w\n' % (Sc2.dir, Sc2.dip, (Sc2.dir+180)%360))
        else:    
            if (Sc1.dir - dir1) % 360 < 180:
                # Sc1 turned conterclokwise
                Sc1rotate = Sc1.rotated(-65)
                f.write('%003d %02d %003d w\n' % (Sc1rotate.dir, Sc1rotate.dip, (Sc1.dir-135)%360))
                Sc1rotate = Sc1.rotated(65)
                f.write('%003d %02d %003d w\n' % (Sc1rotate.dir, Sc1rotate.dip, (Sc1.dir-45)%360))
            else:
                # Sc1 turned clokwise
                Sc1rotate = Sc1.rotated(65)
                f.write('%003d %02d %003d w\n' % (Sc1rotate.dir, Sc1rotate.dip, (Sc1.dir-135)%360))
                Sc1rotate = Sc1.rotated(-65)
                f.write('%003d %02d %003d w\n' % (Sc1rotate.dir, Sc1rotate.dip, (Sc1.dir-45)%360))
            if (Sc2.dir - dir2) % 360 < 180:
                # Sc1 turned conterclokwise
                Sc2rotate = Sc2.rotated(-65)
                f.write('%003d %02d %003d w\n' % (Sc2rotate.dir, Sc2rotate.dip, (Sc2.dir-135)%360))
                Sc2rotate = Sc2.rotated(65)
                f.write('%003d %02d %003d w\n' % (Sc2rotate.dir, Sc2rotate.dip, (Sc2.dir-45)%360))
            else:
                # Sc1 turned clokwise
                Sc2rotate = Sc2.rotated(65)
                f.write('%003d %02d %003d w\n' % (Sc2rotate.dir, Sc2rotate.dip, (Sc2.dir-135)%360))
                Sc2rotate = Sc2.rotated(-65)
                f.write('%003d %02d %003d w\n' % (Sc2rotate.dir, Sc2rotate.dip, (Sc2.dir-45)%360))
        f.write('%003d %02d pz 0,0,1\n' % (L_1.dir, L_1.dip))
        f.write('%003d %02d pz 0.5,0,0.5\n' % (L_2.dir, L_2.dip))
        f.write('%003d %02d pz 1,0,0\n' % (L_3.dir, L_3.dip))
        f.close

else:
    if abs(Sc1.dir - Sc2.dir)< -180 :
        Sc1.dir -= 180
        Sc2.dir -= 180
    if (Sc1.dir < L_1.dir and L_1.dir < Sc2.dir) or (Sc1.dir < (L_1.dir-180) and (L_1.dir-180) < Sc2.dir):
        L_3, L_1 = L_1, L_3

    sys.stdout.write('sigma1   sigma2   sigma3\n')
    sys.stdout.write('%003d %02d   %003d %02d   %003d %02d\n' % (L_1.dir, L_1.dip, L_2.dir, L_2.dip, L_3.dir, L_3.dip))

    if options.ofile:
        f = open(options.ofile, 'w')
        f.write('%003d %02d l\n' % (Sc1.dir, Sc1.dip))
        f.write('%003d %02d l\n' % (Sc2.dir, Sc2.dip))
        f.write('%003d %02d pz 0,0,1\n' % (L_1.dir, L_1.dip))
        f.write('%003d %02d pz 0.5,0,0.5\n' % (L_2.dir, L_2.dip))
        f.write('%003d %02d pz 1,0,0\n' % (L_3.dir, L_3.dip))
        f.close


